package com.geeyuu.android.service;

import java.lang.ref.WeakReference;
import java.util.List;

import android.app.ActivityManager;
import android.app.ActivityManager.RunningServiceInfo;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;

import com.geeyuu.android.activity.BaseActivity.BaseHandler;
import com.geeyuu.android.utils.LogUtil;

public class ServiceManager {
    
    private static final String TAG = "ServiceManager";
    private Class<? extends BaseService> mServiceClass;
    private Context mActivity;
    private boolean mIsBound;
    private Messenger mService = null;
    private BaseHandler mIncomingHandler = null;
    private final Messenger mMessenger = new Messenger(new IncomingHandler(this));
    
    public ServiceManager(Context context, Class<? extends BaseService> serviceClass, BaseHandler incomingHandler) {
        this.mActivity = context;
        this.mServiceClass = serviceClass;
        this.mIncomingHandler = incomingHandler;
        if (isServiceRunning()) {
            doBindService();
        }else{
            doStartService();
            doBindService();
        }
    }
    
    private static class IncomingHandler extends Handler {
        private final WeakReference<ServiceManager> serviceManager;
        public IncomingHandler(ServiceManager serviceManager) {
            this.serviceManager = new WeakReference<ServiceManager>((ServiceManager) (serviceManager));
        }
        @Override
        public void handleMessage(Message msg) {
            if (serviceManager.get().mIncomingHandler != null) {
                serviceManager.get().mIncomingHandler.handleMessage(msg);
            }
        }
    }
    
    private ServiceConnection mConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName className, IBinder service) {
            mService = new Messenger(service);
            try {
                Message msg = Message.obtain(null, BaseService.MSG_REGISTER_CLIENT);
                msg.obj = mIncomingHandler.tag;
                msg.replyTo = mMessenger;
                mService.send(msg);
                //call back
                mIncomingHandler.sendEmptyMessage(-1);
            } catch (Exception e) {
                LogUtil.e(TAG, "绑定返回出错", e);
            }
        }
        @Override
        public void onServiceDisconnected(ComponentName className) {
            mService = null;
        }
    };
    
    private boolean isServiceRunning() {
        ActivityManager manager = (ActivityManager) mActivity.getSystemService(Context.ACTIVITY_SERVICE);
        List<RunningServiceInfo> runningServiceInfos = manager.getRunningServices(Integer.MAX_VALUE);
        for (RunningServiceInfo service : runningServiceInfos) {
            if (mServiceClass.getName().equals(service.service.getClassName())) {
                return true;
            }
        }
        return false;
    }
    
    public void sendMsgToService(Message msg) throws RemoteException {
        if (mIsBound) {
            if (mService != null) {
                mService.send(msg);
            }
        }
    }
    
    private void doStartService() {
        mActivity.startService(new Intent(mActivity, mServiceClass));       
    }
    
    private void doBindService() {
        mActivity.bindService(new Intent(mActivity, mServiceClass), mConnection, Context.BIND_AUTO_CREATE);
        mIsBound = true;
    }
    
    public void doUnbindService(String tag) {
        if (mIsBound) {
            if (mService != null) {
                try {
                    Message msg = Message.obtain(null, BaseService.MSG_UNREGISTER_CLIENT);
                    msg.replyTo = mMessenger;
                    msg.obj = tag;
                    mService.send(msg);
                } catch (Exception e) {
                    LogUtil.e(TAG, "解除绑定出错", e);
                }
            }
            mActivity.unbindService(mConnection);
            mIsBound = false;
        }
    }

}
